#    Copyright 2013 Tri-County Electric Cooperative, St. Matthews, South Carolina
#    This file is part of COOPIP.
#    COOPIP is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#    COOPIP is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#    You should have received a copy of the GNU General Public License
#    along with COOPIP.  If not, see <http://www.gnu.org/licenses/>.

#************************BEGIN Add Include Files to Path************************
import sys
NeededPaths=['/opt/coopip/djangoproject/include', '/opt/coopip/djangoproject']
for path in NeededPaths:
    if(not path in sys.path):
        sys.path.append(path)
#************************END   Add Include Files to Path************************
import os, csv, shutil, datetime, time, reportlab, djangoproject.settings, random
from django.contrib.gis.db import models
from django.contrib.gis.geos import *
from django.http import HttpResponse
from django.contrib import admin
from django.template import Context, loader
import djangoproject.settings
import _mysql as mysql
from models import *
from django import forms
import django
import djangoproject
import COOPIP_Form, COOPIP_DynamicTemplate, COOPIP_Authentication, COOPIP_FormDispatch, COOPIP_Misc
import Misc, MeterPing
from django.db import transaction #see django bug #9964; these pages are SELECT only, so turnin over to autocommit shouldn't cause issues
import AMR

def MainMenu(request):
    """MainMenu is the main selection screen for Dispatch Functions."""
    Permission, LoginStatus, Username = COOPIP_Authentication.COOPIPAuthenticate(request, djangoproject.settings.StatusGroups)
    if(not Permission):
        return Misc.DefaultMainPage(LoginStatus)
    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchmain.html')
    c = Context({'LoginStatus': LoginStatus})
    return HttpResponse(t.render(c))

def ViewCameras(request):
    """menu of available camera views"""
    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchviewcameras.html')
    c = Context({})
    return HttpResponse(t.render(c))

def ViewCamerasStMatthewsRegion(request):
    """cameras in substations around SMO"""
    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchviewcamerasstmatthewsregion.html')
    c = Context({})
    return HttpResponse(t.render(c))


def ViewCamerasRichlandRegion(request):
    """cameras in substations around RDO"""
    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchviewcamerasrichlandregion.html')
    c = Context({})
    return HttpResponse(t.render(c))

def ViewCamerasSanteeRegion(request):
    """cameras in substations around SDO"""
    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchviewcamerassanteeregion.html')
    c = Context({})
    return HttpResponse(t.render(c))

def DisplayCameras(request):
    """For camera display in Dispatch"""
    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchdisplaycameras.html')
    c = Context({})
    return HttpResponse(t.render(c))

def DisplayMap(request):
    """For large map on display in Dispatch"""
    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchdisplaymap.html')
    c = Context({})
    return HttpResponse(t.render(c))

def ViewMap(request):
    """System map using OpenLayers"""
    Permission, LoginStatus, Username = COOPIP_Authentication.COOPIPAuthenticate(request, djangoproject.settings.StatusGroups)
    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchviewmap.html')
    c = Context({})
    return HttpResponse(t.render(c))

@transaction.autocommit()
def NetworkStatus(request):
    """View optimized for displaying the dispatch board on large dispatch displays
    JQuery's initial call for dispatch displays.  Once loaded, that page's script issues a request to NetworkStatusData"""
    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchnetworkstatus.html')
    c = Context({})
    return HttpResponse(t.render(c))

def IncreaseAlertStatus(AlertStatus, NewStatus):
    if(NewStatus == 'down' or AlertStatus == 'down'):
        return 'down'
    if(AlertStatus == 'alert' or NewStatus == 'alert'):
        return 'alert'
    return NewStatus

@transaction.autocommit()
def NetworkStatusData(request):
    """Shows list of substations and their current status, AMR commands, radio percentages, and monitoring equipment"""
    import datetime

    StartDate=datetime.datetime.now() - datetime.timedelta(days=2)
    SummaryReport=[]

    Substations=list(AMR.Scemain.objects.all().order_by('subname'))
    Headings=['Substation', 'Status', 'State', 'Cmd/Src', 'Radio', 'Alarm','WebSensor','Voltage','Temp','Humidity']


    SubstationStatusTextRefDictionary={} #Key = substatus, value = subconnectstatustext
    AMRSubstationStatuses=list(AMR.Substatetextxref.objects.all())
    for i in AMRSubstationStatuses:
        SubstationStatusTextRefDictionary[str(i.substatus)] = str(i.subconnectstatustext)

    SubstationStateTextRefDictionary = {} #Key = substate, value = subconnectstatetext
    AMRSubstationStates=list(AMR.Substatetextxref.objects.all())
    for i in AMRSubstationStates:
        SubstationStateTextRefDictionary[str(i.substate)] = str(i.subconnectstatetext)

    AMROutCommandDictionary = {}  #Key = subid, value = Number of Commands
    OutCommands=list(AMR.Outcmd.objects.exclude(funccode=300))
    for i in OutCommands:
        if(not str(i.subid) in AMROutCommandDictionary):
            AMROutCommandDictionary[str(i.subid)] = 0
        AMROutCommandDictionary[str(i.subid)] += 1

    AMROutSearchDictionary = {}  #Key = subid, value = Number of Searches
    OutSearches=list(AMR.Outcmd.objects.filter(funccode=300))
    for i in OutSearches:
        if(not str(i.subid) in AMROutSearchDictionary):
            AMROutSearchDictionary[str(i.subid)] = 0
        AMROutSearchDictionary[str(i.subid)] += 1

    for substation in Substations:
        AlertStatus='ok'
        if(substation.subname == 'UNKNOWN'):
            continue 
        row=[]
        row.append(substation.subname)

        SubstationStatus=SubstationStatusTextRefDictionary[str(substation.substatus)]

        if(not SubstationStatus == 'Online'):
            AlertStatus=IncreaseAlertStatus(AlertStatus, 'down')
        SubstationState=SubstationStateTextRefDictionary[str(substation.substate)]

        try:
            OutCommands=AMROutCommandDictionary[str(substation.subid)]
        except KeyError:
            OutCommands=0

        try:
            MeterSearches=AMROutSearchDictionary[str(substation.subid)]
        except KeyError:
            MeterSearches=0
        row.append(str(SubstationStatus))
        row.append(str(SubstationState))

        row.append(str(OutCommands) + ' / ' + str(MeterSearches))
        if(OutCommands > 300):
            AlertStatus=IncreaseAlertStatus(AlertStatus, 'alert')
        if substation.subname == 'RICHLAND':
            Switch = NetworkDevice.objects.filter(ActiveIndicator=True).filter(NetworkDeviceModel__Name='Ubiquiti ToughSwitch').filter(AMRSubstationName=substation.subname)[0]
            RadioInfo, Percent = Switch.GetRecentStatus()
        else:
            Radios = NetworkDevice.objects.filter(ActiveIndicator=True).filter(NetworkDeviceModel__Name__in=['ProST Radio', 'Rocket M5 Radio', 'Rocket M5 GPS Radio']).filter(AMRSubstationName=substation.subname)
            try:
                RadioInfo, Percent=Radios[0].GetRecentStatus()
            except:
                RadioInfo, Percent='N/A', None

        row.append(str(RadioInfo))

        if(Percent and Percent < 98):
           AlertStatus=IncreaseAlertStatus(AlertStatus, 'alert')
        NetworkDevices=NetworkDevice.objects.filter(NetworkDeviceModel__Name='DSC 1832 Alarm').filter(AMRSubstationName=substation.subname)
        if(not NetworkDevices):
            AlarmInfo='N/A'
            ActiveEventString=''
        else:
            AlarmInfo=NetworkDevices[0].GetRecentStatus()
            AlarmInfo=str(AlarmInfo[0]) + ' ' + str(AlarmInfo[1])
            if(AlarmEventHistory.objects.filter(NetworkDevice=NetworkDevices[0]).filter(CloseDateTime__isnull=True)):
                ActiveEventString='*Active Event* '
            else:
                ActiveEventString=''
        row.append(ActiveEventString + AlarmInfo)
        try:
            NetworkDevices=NetworkDevice.objects.filter(NetworkDeviceModel__Name='SensorProbe2').filter(AMRSubstationName=substation.subname)
            SensorProbeStatus, Voltage, Temperature, Humidity=NetworkDevices[0].GetRecentStatus()
            SensorProbeVoltage=str(Voltage) + ' V'
            SensorProbeTemperature=str(Temperature) + ' F'
            SensorProbeHumidity=str(Humidity) + '%'
        except:
            SensorProbeStatus, SensorProbeVoltage, SensorProbeTemperature, SensorProbeHumidity='N/A','','',''
        row.append(SensorProbeStatus)
        row.append(SensorProbeVoltage)
        row.append(SensorProbeTemperature)
        row.append(SensorProbeHumidity)
        row.insert(0, AlertStatus)
        SummaryReport.append(row)
    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchnetworkstatusdata.html')
    c = Context({'SummaryReport': SummaryReport, 'Headings': Headings})
    return HttpResponse(t.render(c))

@transaction.autocommit()
def DisplayOutage(request):
    """View optimized for displaying the dispatch board on large dispatch displays
    JQuery's initial call for dispatch displays.  Once loaded, that page's script issues a request to DisplayOutageData"""
    EditorGroups=djangoproject.settings.DispatchEditorGroups
    Permission, LoginStatus, Username = COOPIP_Authentication.COOPIPAuthenticate(request, EditorGroups)
    #When using authentication, check for application permission here.
    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchdisplayoutage.html')
    c = Context({})
    return HttpResponse(t.render(c))

def IncidentMeterPingStatusString(meter):
    TimeString = COOPIP_Misc.StringTimeSinceEvent(datetime.datetime.now(), meter.LastPingResponseDateTime)
    
    if(meter.IncidentSymbology in ['failed', 'failed_with_open_incident']):
        return TimeString + ' Failure'
    elif(meter.IncidentSymbology in ['success', 'open_incident']):
        return TimeString + ' Success'
    else:
        return TimeString + ' ' + str(meter.IncidentSymbology)


def GetGISCircuitNumberFromIncident(incident):
    meter = djangoproject.models.ipbase.Meter.objects.filter(SerialNumber=incident.meter_number.lstrip('0'))
    if(meter):
        return str(meter[0].GISCircuitNumber)
    else:
        return str(incident.substation) + '-' + str(incident.feeder)

@transaction.autocommit()
def DisplayOutageData(request):
    """Shows incidents from the OMS along with details"""
    import datetime
    import OMS
    import random
    Report=[]
    Headings=['# Out','ID','Sub-Fdr','District','Duration','Map Location','Service Location','Meter','Meter Ping Status','Account Number']
    ActiveIncidents=OMS.ImsIncident.objects.all()
    CurrentTime=datetime.datetime.now()

    GroupIncidents = OMS.ImsIncident.objects.filter(incident_id__startswith='G').order_by('substation', 'feeder')
    DeviceIncidents = OMS.ImsIncident.objects.filter(incident_id__startswith='D').filter(group_id='N').order_by('substation', 'feeder')
    SingleIncidents = OMS.ImsIncident.objects.filter(incident_id__startswith='C').filter(group_id='N').filter(device_id_phase_a__isnull=True, device_id_phase_b__isnull=True, device_id_phase_c__isnull=True).order_by('substation', 'feeder')
    for group in GroupIncidents:
        row=[]
        row.append('group')
        row.append(group.consumers_affected)
        row.append(group.incident_id)
        incident = OMS.ImsIncident.objects.filter(group_id=group.incident_id)[0]
        row.append(GetGISCircuitNumberFromIncident(incident))

        row.append(group.district)
        DurationDifference=CurrentTime - group.start_date
        Duration=int(DurationDifference.total_seconds())
        row.append(str(Duration/60/60).rjust(2,'0') + ':' + str(Duration/60%60).rjust(2,'0'))
        row.append(incident.map_location)
        row.append(incident.service_location)
        row.append(incident.meter_number)
        row.append(incident.account_name)
        row.append(incident.acctno)
        Report.append(row)
    for device in DeviceIncidents:
        row=[]
        row.append('device')
        row.append(device.consumers_affected)
        row.append(device.incident_id)
        IncidentPool = OMS.ImsIncident.objects.filter(
                       device_id_phase_a=device.incident_id) | OMS.ImsIncident.objects.filter(
                       device_id_phase_b=device.incident_id) | OMS.ImsIncident.objects.filter(
                       device_id_phase_c=device.incident_id)
        if(IncidentPool):
            row.append(GetGISCircuitNumberFromIncident(IncidentPool[0]))
        else:
            row.append(str(device.substation) + '-' + str(device.feeder))
        row.append(device.district)
        DurationDifference=CurrentTime - device.start_date
        Duration=int(DurationDifference.total_seconds())
        row.append(str(Duration/60/60).rjust(2,'0') + ':' + str(Duration/60%60).rjust(2,'0'))

        try:
            incident = IncidentPool[0]
            row.append(incident.map_location)
            row.append(incident.service_location)
            row.append(incident.meter_number)
            row.append(incident.account_name)
            row.append(incident.acctno)
        except IndexError: #device outages may not have incidents grouped under them; grouped outages by definition contain multiple incidents
            pass
        Report.append(row)
    for incident in SingleIncidents:
        row=[]
        row.append('single')
        row.append('') #db shows consumers_affected as 0 for single incidents
        row.append(incident.incident_id)
        row.append(GetGISCircuitNumberFromIncident(incident))
        row.append(incident.district)
        DurationDifference=CurrentTime - incident.start_date
        Duration=int(DurationDifference.total_seconds())
        row.append(str(Duration/60/60).rjust(2,'0') + ':' + str(Duration/60%60).rjust(2,'0'))
        row.append(incident.map_location)
        row.append(incident.service_location)
        row.append(incident.meter_number)
        meter = Meter.objects.filter(SerialNumber=incident.meter_number.lstrip('0'))
        if(meter):
            row.append(IncidentMeterPingStatusString(meter[0]))
        else:
            row.append('UNKNOWN')
        row.append(incident.acctno)
        Report.append(row)
    t=loader.get_template('/opt/coopip/djangoproject/templates/dispatchdisplayoutagedata.html')
    c=Context({'Headings': Headings, 'Report': Report})
    return HttpResponse(t.render(c))

@transaction.autocommit()
def DisplayMessageBoard(request):
    """View optimized for displaying the dispatch board on large dispatch displays
    JQuery's initial call for dispatch displays.  Once loaded, that page's script issues a request to DisplayMessageBoardData"""
    import datetime
    EditorGroups=djangoproject.settings.DispatchEditorGroups
    Permission, LoginStatus, Username = COOPIP_Authentication.COOPIPAuthenticate(request, EditorGroups)
    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchdisplaymessageboard.html')
    c = Context({})
    return HttpResponse(t.render(c))

def StringToList(InputString):
    CleanString=InputString.replace('\r','')
    CleanList=CleanString.split('\n')
    return CleanList

@transaction.autocommit()
def DisplayMessageBoardData(request):
    """Shows useful lists as defined by Dispatch"""
    dispatchBoard=djangoproject.models.intranet.DispatchBoard.objects.all().order_by('-CreateDateTime')[0]
    crewstring=(dispatchBoard.CrewList).replace('\r','')
    newstringlist=crewstring.split('\n\n')
    TempCrewList=[]
    for n in newstringlist:
        sublist=n.split('\n')
        TempCrewList.append(sublist)
    counter=0
    FinalCrewList=[]
    for crewsublist in TempCrewList:
        counter+=1
        row1=[]
        for entry in crewsublist:
            row2=[]
            if '*' in entry:
                crewleaderstatus='crewleader'
            else:
                crewleaderstatus='crewmember'
            row2.append(crewleaderstatus)
            row2.append(entry.replace('*',''))
            row1.append(row2)
        row1.insert(0,'crew'+str(counter))
        FinalCrewList.append(row1)
    ServiceWorkerList=StringToList(dispatchBoard.ServiceWorkerList)
    EngineerList=StringToList(dispatchBoard.EngineerList)
    OutOfOfficeList=StringToList(dispatchBoard.OutOfOffice)
    ServiceWorkerHoursList=StringToList(dispatchBoard.ServiceWorkerHours)
    OnCallList=StringToList(dispatchBoard.OnCallList)

    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchdisplaymessageboarddata.html')
    c = Context({'DispatchBoardCrewList': FinalCrewList, 'ServiceWorkers': ServiceWorkerList,
                 'Engineers': EngineerList, 'OutOfOffice':OutOfOfficeList, 'ServiceWorkerHours': ServiceWorkerHoursList, 'OnCall': OnCallList})
    return HttpResponse(t.render(c))


def EditMessageBoard(request):
    """View that allows users to View the Dispatch Boards and Dispatchers to edit them."""
    import datetime
    EditorGroups=djangoproject.settings.DispatchEditorGroups
    Permission, LoginStatus, Username = COOPIP_Authentication.COOPIPAuthenticate(request, EditorGroups)
    if(not Permission):  
        return IntranetNoPermission(LoginStatus, Permission)
    SpecialBuildFormDataDict={'request': request}
    form=COOPIP_Form.BuildDynamicForm(request, 'DispatchBoard', SpecialBuildFormDataDict)
    COOPIP_FormDispatch.ProcessMessageBoardForm(form, Username, request)
    form=COOPIP_FormDispatch.PopulateMessageBoardForm(form)

    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatcheditmessageboard.html')
    c = Context({'LoginStatus': LoginStatus, 'form': form, 'Permission': Permission})
    return HttpResponse(t.render(c))

def EditVehicles(request):
    """View that allows dispatchers to view vehicle data (current speed, bearing, last log read time) and edit select fields"""
    Permission, LoginStatus, Username = COOPIP_Authentication.COOPIPAuthenticate(request, djangoproject.settings.StatusGroups)
    if(not Permission):  
        return Misc.DefaultMainPage(LoginStatus)
    Vehicles = Vehicle.objects.all().order_by('Number')
    SpecialBuildFormDataDict={}
    SpecialBuildFormDataDict['Vehicles'] = Vehicles
    SpecialBuildFormDataDict['request'] = request
    form=COOPIP_Form.BuildDynamicForm(request, 'DispatchVehicles', SpecialBuildFormDataDict)
    FormPermission, FormLoginStatus, FormUserName = COOPIP_Authentication.COOPIPAuthenticate(request, djangoproject.settings.DispatchEditorGroups)
    if(FormPermission):
        COOPIP_FormDispatch.ProcessVehicleForm(form, Username, SpecialBuildFormDataDict['Vehicles'])
    Vehicles = Vehicle.objects.all().order_by('Number')
    form=COOPIP_FormDispatch.PopulateVehicleForm(form, Vehicles)
    COOPIP_DynamicTemplate.UpdateVehicleTemplate(Username, Vehicles)
    t = loader.get_template('/opt/coopip/djangoproject/templates/dynamic_dispatcheditvehicles_' + Username + '.html')
    c = Context({'LoginStatus': LoginStatus, 'form': form, 'Permission': Permission})
    return HttpResponse(t.render(c))

def EditCrewLogs(request):
    """View that allows users to View the Dispatch Boards and Dispatchers to edit them."""
    import datetime
    EditorGroups=djangoproject.settings.DispatchEditorGroups
    Permission, LoginStatus, Username = COOPIP_Authentication.COOPIPAuthenticate(request, EditorGroups)
    StartTime=datetime.datetime.now()- datetime.timedelta(hours=12)
    DispatchCrewLogs=DispatchCrewLog.objects.filter(CreateDateTime__gte=StartTime
                                  ).exclude(DeletedIndicator=True).order_by('CrewNumber', 'TruckNumber')
    if(not Permission):  #If no permission, then just display the dispatch crew logs
        t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchcrewlogviewonly.html')
        c = Context({'LoginStatus': LoginStatus, 'Permission': Permission, 'DispatchCrewLogs': DispatchCrewLogs})
        return HttpResponse(t.render(c))
    SpecialBuildFormDataDict={'request': request, 'DispatchCrewLogs': DispatchCrewLogs}
    form=COOPIP_Form.BuildDynamicForm(request, 'DispatchCrewLog', SpecialBuildFormDataDict)  
    COOPIP_FormDispatch.ProcessCrewLogForm(form, Username, request)
    DispatchCrewLogs=DispatchCrewLog.objects.filter(CreateDateTime__gte=StartTime).exclude(DeletedIndicator=True).order_by('CrewNumber', 'TruckNumber')
    SpecialBuildFormDataDict={'request': request, 'DispatchCrewLogs': DispatchCrewLogs}
    COOPIP_DynamicTemplate.UpdateCrewLogTemplate(Username, DispatchCrewLogs.count())
    form=COOPIP_Form.BuildDynamicForm(request, 'DispatchCrewLog', SpecialBuildFormDataDict)  #Rebuild the form in case a new CrewLog was added
    form=COOPIP_FormDispatch.PopulateCrewLogForm(form, DispatchCrewLogs)
    t = loader.get_template('/opt/coopip/djangoproject/templates/dynamic_dispatchcrewlog_' + Username + '.html')
    c = Context({'LoginStatus': LoginStatus, 'form': form, 'Permission': Permission})
    return HttpResponse(t.render(c))

def TableGetDateTime(DateTime):
    """Attempts to return a formatted DateTime if one exists"""
    try:
        ReturnObject = DateTime.strftime('%H:%M')
        return ReturnObject
    except:
        return ''


def ViewCrewLogHistory(request):
    """View that allows users to View older Crew Log entries; No editing"""
    EditorGroups=djangoproject.settings.DispatchEditorGroups
    Permission, LoginStatus, Username = COOPIP_Authentication.COOPIPAuthenticate(request, EditorGroups)
    DispatchCrewLogs=djangoproject.models.intranet.DispatchCrewLog.objects.filter(CreateDateTime__gte=datetime.datetime.now()- datetime.timedelta(days=7)
                     ).exclude(DeletedIndicator=True).order_by('-CreateDateTime')    
    if(not Permission):  #If no permission, then just display the dispatch crew logs
        t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchcrewlogviewonly.html')
        c = Context({'LoginStatus': LoginStatus, 'Permission': Permission, 'DispatchCrewLogs': DispatchCrewLogs})
        return HttpResponse(t.render(c))
    Headings=['Log Created', 'Crew #','Truck', 'Employees','EnRoute','Arrival', 'Departure', 'Location', 'Pole #', 'Comments', 'Back At Office', 'Address']
    SummaryReport=[]
    for log in DispatchCrewLogs:
        row=[]
        row.append(log.CreateDateTime.strftime('%m/%d/%Y'))
        row.append(log.CrewNumber)
        row.append(log.TruckNumber)
        row.append(log.Employees)
        row.append(TableGetDateTime(log.EnRouteDateTime))
        row.append(TableGetDateTime(log.ArriveAtLocationDateTime))
        row.append(TableGetDateTime(log.DepartLocationDateTime))
        row.append(log.LocationDescription)
        if not log.PoleNumber == 0:
            row.append(log.PoleNumber)
        else:
            row.append('')
        row.append(log.Comments)
        row.append(TableGetDateTime(log.BackAtOfficeDateTime))
        row.append(log.Address)

        SummaryReport.append(row)
    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchcrewloghistory.html')
    c = Context({'LoginStatus': LoginStatus, 'Permission': Permission, 'Headings': Headings, 'SummaryReport': SummaryReport})
    return HttpResponse(t.render(c))



@transaction.autocommit()
def DisplayMeterPing(request):
    """View optimized for displaying the dispatch board on large dispatch displays"""
    import datetime
    Permission, LoginStatus, Username = COOPIP_Authentication.COOPIPAuthenticate(request, djangoproject.settings.StatusGroups)
    
    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchdisplaymeterping.html')
    c = Context({})
    return HttpResponse(t.render(c))

@transaction.autocommit()
def DisplayMeterPingWithoutGroups(request):
    """View optimized for displaying the dispatch board on large dispatch displays"""
    import datetime
    Permission, LoginStatus, Username = COOPIP_Authentication.COOPIPAuthenticate(request, djangoproject.settings.StatusGroups)
    
    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchdisplaymeterpingwithoutgroups.html')
    c = Context({})
    return HttpResponse(t.render(c))


def MeterPingGroupMeters(SortedFailedMetersForDisplay):
    MinimumGroupSize = 10
    CountByCircuitDict = {} #Key = Circuit, Value = Count
    GroupOutageList=[]
    for meterpingdisplay in SortedFailedMetersForDisplay:
        if(not CountByCircuitDict.has_key(meterpingdisplay[3])):
            CountByCircuitDict[meterpingdisplay[3]] = 0
        if(meterpingdisplay[2] == 'fail'):
            CountByCircuitDict[meterpingdisplay[3]] = CountByCircuitDict[meterpingdisplay[3]] + 1
            if(CountByCircuitDict[meterpingdisplay[3]] > MinimumGroupSize):
                meterpingdisplay[0] = 'GROUP--SKIP'
    for key in CountByCircuitDict:
        if(CountByCircuitDict[key] > MinimumGroupSize - 1):
            SortedFailedMetersForDisplay.insert(0, [str(CountByCircuitDict[key]) + ' Meters', '', '****', key, '', ''])
        


def DisplayMeterPingDataWithoutGroups(request):
    return DisplayMeterPingData(request, GroupMeters=False)




@transaction.autocommit()
def DisplayMeterPingData(request, AMRFailureIndicator=False, SubstationFailureIndicator=False, GroupMeters=True):
    Permission, LoginStatus, Username = COOPIP_Authentication.COOPIPAuthenticate(request, djangoproject.settings.StatusGroups)
    Now=datetime.datetime.now()
    TotalMeters=Meter.objects.exclude(Symbology='deleted').count()
    MetersPingedInPastHour=Meter.objects.filter(LastPingResponseDateTime__gte=(Now - datetime.timedelta(hours=1))).exclude(Symbology='deleted').count()
    SuccessfulMeterPings=Meter.objects.filter(IncidentSymbology__in=['success', 'open_incident']).count()
    SuccessfulBackFedMeterPings=Meter.objects.filter(IncidentSymbology__in=['BF-success', 'BF-open_incident']).count()
    FailedMeterPings=Meter.objects.filter(IncidentSymbology__in=['failed', 'failed_with_open_incident']).count()
    AMRFailureMeterPings=Meter.objects.filter(IncidentSymbology='amrfailure').count()
    SubstationFailureMeterPings=Meter.objects.filter(IncidentSymbology='substationfailure').count()
    ServiceOrderMeterPings=Meter.objects.filter(IncidentSymbology='serviceorder').count()
    OtherMeterPings=Meter.objects.exclude(IncidentSymbology__in=['success', 'failed', 'amrfailure', 'substationfailure', 'deleted', 'open_incident', 'serviceorder', 
                                                                 'failed_with_open_incident', 'BF-success', 'BF-open_incident']).count()
    Now=datetime.datetime.now()
    if(AMRFailureIndicator):
        PageHeading='Meter Ping AMR Failure Report:  ' + str(Now)[:16]
        FailedMeters=Meter.objects.filter(Symbology='amrfailure').order_by('GISCircuitNumber', 'GISPhaseCode', 'SerialNumber')
    elif(SubstationFailureIndicator):
        PageHeading='Meter Ping Substation Failure Report:  ' + str(Now)[:16]
        FailedMeters=Meter.objects.filter(Symbology='substationfailure').order_by('GISCircuitNumber', 'GISPhaseCode', 'SerialNumber')
    else:
        PageHeading='Meter Ping Failure Report:  ' + str(Now)[:16]
        FailedMeters=Meter.objects.filter(Symbology='failed') | Meter.objects.filter(Description__isnull=False).exclude(Description='') | Meter.objects.filter(IncidentSymbology__icontains='incident')
    FailedMeters.order_by('GISCircuitNumber', 'GISPhaseCode', 'SerialNumber')
    #Failed Meters is not sorting at all, so sort
    #FailedMeters=Meter.objects.all()[:500]  #Use for testing columns

    SortedFailedMetersForDisplay=[]
    for i in FailedMeters:
        SortedFailedMetersForDisplay.append([MeterPing.StringMeterNumber(i), COOPIP_Misc.StringTimeSinceEvent(Now, i.LastPingResponseDateTime),
                                             MeterPing.StringLastResponse(i).replace('serviceorder', 'S/O'), i.GISCircuitNumber, i.GISPhaseCode, i.Description])
    SortedFailedMetersForDisplay.sort(key = lambda row: str(row[3]) + str(row[0]))

    if(GroupMeters):
        MeterPingGroupMeters(SortedFailedMetersForDisplay)

    LeftFailedReport = []
    MiddleFailedReport = []
    RightFailedReport = []
    Count = 0
    FirstColumnCutOff=30
    SecondColumnCutOff=66

    for i in SortedFailedMetersForDisplay:
        if(i[0] == 'GROUP--SKIP'):
            continue
        if(Count < FirstColumnCutOff):
            LeftFailedReport.append(i)
        elif(Count < SecondColumnCutOff):
            MiddleFailedReport.append(i)
        else:
            RightFailedReport.append(i)
        Count = Count + 1
    ColumnHeadings = ['Meter', 'Last', 'Result', 'Circuit', 'Phase', 'Notes']
    LeftFailedReport.insert(0, ColumnHeadings)
    if(MiddleFailedReport):
        MiddleFailedReport.insert(0, ColumnHeadings)
    if(RightFailedReport):
        RightFailedReport.insert(0, ColumnHeadings)


    MeterPingRate=djangoproject.models.ipbase.COOPIPSetting.GetPingRate()
    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchdisplaymeterpingdata.html')
    c = Context({'MetersPingedInPastHour': MetersPingedInPastHour, 'SuccessfulMeterPings': SuccessfulMeterPings, 'FailedMeterPings': FailedMeterPings,
                 'AMRFailureMeterPings': AMRFailureMeterPings, 'SubstationFailureMeterPings': SubstationFailureMeterPings,
                 'OtherMeterPings': OtherMeterPings, 'ServiceOrderMeterPings': ServiceOrderMeterPings,  
                 'LeftFailedReport': LeftFailedReport, 'MiddleFailedReport': MiddleFailedReport, 'RightFailedReport': RightFailedReport,
                 'PageHeading': PageHeading, 'MeterPingRate': MeterPingRate, 'SuccessfulBackFedMeterPings': SuccessfulBackFedMeterPings,
                 'TotalMeters': TotalMeters})
    return HttpResponse(t.render(c))

def EditAlarms(request):
    """View that allows dispatch/others to arm/disarm alarms and to acknowledge alarm alerts in a tabular form"""
    import datetime
    EditorGroups=djangoproject.settings.DispatchEditorGroups
    Permission, LoginStatus, Username = COOPIP_Authentication.COOPIPAuthenticate(request, EditorGroups)
    if(not Permission):  
        return Misc.DefaultMainPage(LoginStatus)
  
    Alarms=NetworkDevice.objects.filter(NetworkDeviceModel__Name='DSC 1832 Alarm').filter(ActiveIndicator=True).order_by('id')

    SpecialBuildFormDataDict={}
    SpecialBuildFormDataDict['Alarms'] = Alarms
    SpecialBuildFormDataDict['request'] = request

    form=COOPIP_Form.BuildDynamicForm(request, 'DispatchAlarm', SpecialBuildFormDataDict)
    COOPIP_FormDispatch.ProcessAlarmForm(form, Username)
    form=COOPIP_FormDispatch.PopulateAlarmForm(form, Alarms)
    #raise(Exception(str(form.data)))
    COOPIP_DynamicTemplate.UpdateAlarmTemplate(Username, Alarms)
    t = loader.get_template('/opt/coopip/djangoproject/templates/dynamic_alarmtable_' + Username + '.html')
    c = Context({'LoginStatus': LoginStatus, 'form': form, 'Permission': Permission})
    return HttpResponse(t.render(c))

def EditAlarmContacts(request):
    """View that allows editing of contact lists and other variables for alarm event notifications"""
    EditorGroups=djangoproject.settings.DispatchEditorGroups
    Permission, LoginStatus, Username = COOPIP_Authentication.COOPIPAuthenticate(request, EditorGroups)
    if(not Permission):  
        return Misc.DefaultMainPage(LoginStatus)
    Groups = AlarmContactGroup.objects.all().order_by('PriorityLevel')
    SpecialBuildFormDataDict={}
    SpecialBuildFormDataDict['Groups'] = Groups
    SpecialBuildFormDataDict['request'] = request
    form=COOPIP_Form.BuildDynamicForm(request, 'DispatchAlarmContacts', SpecialBuildFormDataDict)
    COOPIP_FormDispatch.ProcessAlarmContactForm(form, Username, SpecialBuildFormDataDict['Groups'])
    Groups = AlarmContactGroup.objects.all()
    form=COOPIP_FormDispatch.PopulateAlarmContactForm(form, Groups)
    COOPIP_DynamicTemplate.UpdateAlarmContactTemplate(Username, Groups)
    t = loader.get_template('/opt/coopip/djangoproject/templates/dynamic_alarmcontact_' + Username + '.html')
    c = Context({'LoginStatus': LoginStatus, 'form': form, 'Permission': Permission})
    return HttpResponse(t.render(c))


def EditOutageAssignment(request):
    """View that allows dispatchers to edit OMSIncidentHistories that point to active incidents"""
    EditorGroups=djangoproject.settings.DispatchEditorGroups
    Permission, LoginStatus, Username = COOPIP_Authentication.COOPIPAuthenticate(request, EditorGroups)
    if(not Permission):  
        return Misc.DefaultMainPage(LoginStatus)
    ActiveIncidents = CurrentOMSIncident.objects.values_list('Recordid', flat=True)
    Logs = OMSIncidentHistory.objects.filter(Recordid__in=ActiveIncidents).order_by('Recordid')

    SpecialBuildFormDataDict={}
    SpecialBuildFormDataDict['Logs'] = Logs
    SpecialBuildFormDataDict['request'] = request

    form=COOPIP_Form.BuildDynamicForm(request, 'DispatchOutageAssignment', SpecialBuildFormDataDict)
    COOPIP_FormDispatch.ProcessOutageAssignmentForm(form, Username, SpecialBuildFormDataDict['Logs'])

    Logs = OMSIncidentHistory.objects.filter(Recordid__in=ActiveIncidents).order_by('Recordid')

    form=COOPIP_FormDispatch.PopulateOutageAssignmentForm(form, Logs)
    COOPIP_DynamicTemplate.UpdateOutageAssignmentTemplate(Username, Logs)

    t = loader.get_template('/opt/coopip/djangoproject/templates/dynamic_dispatcheditoutageassignment_' + Username + '.html')
    c = Context({'LoginStatus': LoginStatus, 'form': form, 'Permission': Permission})
    return HttpResponse(t.render(c))


def ViewAlarmHistory(request):
    import cPickle
    """Report of all Alarm incidents"""
    EditorGroups=djangoproject.settings.DispatchEditorGroups
    Permission, LoginStatus, Username = COOPIP_Authentication.COOPIPAuthenticate(request, EditorGroups)
    if(not Permission):  
        return Misc.DefaultMainPage(LoginStatus)
    GenericReportTitle= 'Dispatch: Substation Alarm History'
    Report=[]
    Devices = NetworkDevice.objects.filter(NetworkDeviceModel__Name='DSC 1832 Alarm')
    for device in Devices:
        Report.append(device.Name)
        Report.append('Date/Time'.ljust(35) + 'Open Zones'.ljust(20))
        History = AlarmHistory.objects.filter(NetworkDevice=device).filter(AlarmStatus__Name='In Alarm').order_by('-CreateDateTime')
        for i in History:
            ZoneDict = i.GetZoneStatusDict()
            if ZoneDict:
                ZoneList = [str(key) for key in ZoneDict]
                ZoneString = ' '.join(ZoneList)
            else:
                ZoneString = ''
            Report.append(str(i.CreateDateTime).ljust(35) + ZoneString.ljust(20))
        Report.append('')
        Report.append('')
    Preformatted='\n'.join(Report)
    #End Data Gathering Tasks
    GenericMessage=''
    t = loader.get_template('/opt/coopip/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))


def EditDynamicCircuitAssignments(request):
    """View that allows dispatch to allow meters to be pinged down alternate paths when circuits are backfed in a tabular form"""
    import datetime
    EditorGroups=djangoproject.settings.DispatchEditorGroups
    Permission, LoginStatus, Username = COOPIP_Authentication.COOPIPAuthenticate(request, EditorGroups)
    if(not Permission):  
        return Misc.DefaultMainPage(LoginStatus)

    form=COOPIP_Form.BuildDynamicForm(request, 'DispatchDynamicCircuitAssignments')
    COOPIP_FormDispatch.ProcessDynamicCircuitAssignmentForm(form, Username)
    form=COOPIP_FormDispatch.PopulateDynamicCircuitAssignmentForm(form)
    MeterPingDynamicCircuits=djangoproject.models.ipbase.MeterPingDynamicCircuit.objects.all().order_by('id')
    t = loader.get_template('/opt/coopip/djangoproject/templates/dispatchdynamiccircuitassignment.html')
    c = Context({'LoginStatus': LoginStatus, 'form': form, 'Permission': Permission, 'MeterPingDynamicCircuits': MeterPingDynamicCircuits})
    return HttpResponse(t.render(c))

